#![allow(dead_code)]

struct IteratorLrn {}

impl IteratorLrn {
    pub fn hello() {
        println!("Iterator learning!");
    }
}

#[cfg(test)]
mod tests {

    #[test]
    fn test_iter() {
        let arr = vec![1, 2, 3, 4, 5, 6, 7, 8, 9];
        let max = arr.into_iter().max();
        println!("max: {}", max.unwrap());
    }

    #[test]
    #[allow(clippy::unnecessary_fold)]
    /// NOTE: fold(1st arg, 2nd closure)
    /// 1st arg: init value
    /// 2nd arg: closure
    fn test_fold() {
        let arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
        let sum = arr.iter().fold(0, |acc, x| acc + x);
        println!("sum: {}", sum);
    }

    #[test]
    /// NOTE: 因为传递给 filter() 的闭包需要用一个引用，并且许多迭代器迭代引用，
    /// 所以这可能导致混乱的情况，其中闭包的类型是双引用：
    fn test_filter() {
        let a = [1, 2, 3];
        let mut b = a.iter().filter(|x| **x > 1);
        let mut c = a.iter().filter(|&x| *x > 1);
        let mut d = a.iter().filter(|&&x| x > 1);
        assert_eq!(b.next(), Some(&2));
        assert_eq!(c.next(), Some(&2));
        assert_eq!(d.next(), Some(&2));
    }

    #[test]
    /// NOTE: take(n), 取迭代器的前n个元素
    fn test_take() {
        let a = [1, 2, 3, 4, 5];
        let mut b = a.iter().take(2);
        assert_eq!(b.next(), Some(&1));
        assert_eq!(b.next(), Some(&2));
        assert_eq!(b.next(), None);
    }

    #[test]
    fn map_test() {
        let a = [1, 2, 3, 4, 5];

        // NOTE: map() 会消耗 self，返回一个新的迭代器
        let mut iter = a.iter().map(|x| 2 * x);

        assert_eq!(iter.next(), Some(2));
        assert_eq!(iter.next(), Some(4));
        assert_eq!(iter.next(), Some(6));
        assert_eq!(iter.next(), Some(8));
        assert_eq!(iter.next(), Some(10));
        assert_eq!(iter.next(), None);

        // NOTE: map_while() 与 map() 类似，但是它使用一个返回 Option 的闭包
        let mut iter_map_while = a.iter().map_while(|x| 16i32.checked_div(*x));

        assert_eq!(iter_map_while.next(), Some(16));
        assert_eq!(iter_map_while.next(), Some(8));
        assert_eq!(iter_map_while.next(), Some(5));
        assert_eq!(iter_map_while.next(), Some(4));
        assert_eq!(iter_map_while.next(), Some(3));
        assert_eq!(iter_map_while.next(), None);
    }
}
